anchor自从在faster rcnn中提出后,被广泛应用于物体检测中,流程可概括如下(one stage)
- 通过backbone和neck(fpn等)网络得到feature map并根据feature map用head网络生成各个尺度的cls score和reg score
- 生成anchor
- 将anchor assign给对应的gt box
- 根据assign result按一定策略sample出正负样本
- 计算loss
(以上英文单词均遵循mmdetection的命名)
而anchor生成在一般的实现中都会使用到三个参数,anchor ratios,anchor strides,scales,其中anchor ratios很好解释,指的就是宽高比(h:s);而anchor strides则有一点绕,我的理解是它指的是感受野的大小,也就是对应feature map对应到原图多少个像素,所以它的值等于原图中anchor的基础大小,这在代码中一般写作base_size,有了base_size,就可以得到一个基础框,此时一般使用((0, 0), (anchor_stride-1, anchor_stride-1))这个框,也就是图中最左上的一个框。。通过这个坐标,可以很轻松的计算出中心(x_ctr, y_ctr),宽和高就是base_size;scales也很简单,就是放缩的尺度,要将宽和高按照各个scale的值放大。
例如:当anchor stride = 4,anchor_ratios = [0.5, 1.0, 2.0],scales = [4, 8, 16]时,首先可以得到一个((0,0),(3,3))的基础框,宽高都为4,将这个4$\times$4的区域按照anchor_ratios进行变换,保证面积不变,宽高比符合要求,可以做如下转换
也可以按如下方式转换
无论用哪种方式都能保证面积不变,而宽高比符合anchor_ratios。将转换后的hs和ws乘上对应的scales,就能得到放缩后的anchor,有三种ratio,三种scale,一共可以得到9个anchor,再根据中心坐标,算出每个anchor的((xmin, ymin),(xmax, ymax))。
得到左上角的所有anchor坐标之后,只需要对他们进行坐标的平移,就能得到整张图片上所有的anchor的坐标,有平移就会涉及到x和y方向的stride,一般将stride设为与anchor_stride相等,也可以根据情况自己设置。
mmdetection中AnchorGenerator类实现的就是这一过程,除此之外,如果坐标在图外显然是invalid的,mmdetection中还对feat_map上有效的anchor进行了计算,该类中仅仅处理了右侧和下侧的边界问题,而对于上侧和左侧的边界,也就是0一侧的判断是在anchor_target.py
中的anchor_inside_flags
函数中处理的,该函数中同样考虑了右侧和下侧的边界,得到的是所有合法anchor。
以下是AnchorGenerator的代码,结合上面的说明理解起来并不困难
|
|